package cn.fengsweb.tokyotyrant
{
	import cn.fengsweb.tokyotyrant.define.TokyoTyrantQueryResultType;
	import cn.fengsweb.tokyotyrant.define.TokyoTyrantCMD;
	import cn.fengsweb.tokyotyrant.define.TokyoTyrantQueryFunctionName;
	
	import flash.utils.ByteArray;
	
	public class TokyoTyrantQuery
	{
		private var _bytes:ByteArray;
		private var _rnum:uint	= 0;
		private var _resultType:String	= TokyoTyrantQueryResultType.KEY_ARRAY;
		
		public function get sendBytes():ByteArray
		{
			return _bytes;
		}
		public function get resultType():String
		{
			return _resultType;
		}
		
		public function TokyoTyrantQuery(tokyoTyrantQueryFunctionName:String="search")
		{
			_bytes	= new ByteArray();
			
			_bytes.writeShort(TokyoTyrantCMD.MISC);
			
			addFunName(tokyoTyrantQueryFunctionName);
		}
		
		public function addCondition(name:String, expr:String, tokyoTyrantQueryConditionType:uint=5):void
		{
			var abuf:ByteArray	= new ByteArray();
				abuf.writeUTFBytes("addcond");
				abuf.writeByte(0);
				abuf.writeUTFBytes(name);
				abuf.writeByte(0);
				abuf.writeUTFBytes(String(tokyoTyrantQueryConditionType));
				abuf.writeByte(0);
				abuf.writeUTFBytes(expr);
			
			addArguments(abuf);
		}
		
		public function setLimit(max:int, skip:int=-1):void
		{
			var abuf:ByteArray	= new ByteArray();
				abuf.writeUTFBytes("setlimit");
				abuf.writeByte(0);
				abuf.writeUTFBytes(String(max));
				abuf.writeByte(0);
				abuf.writeUTFBytes(String(skip));
			
			addArguments(abuf);
		}
		
		public function count():void
		{
			_resultType = TokyoTyrantQueryResultType.COUNT;
			
			var abuf:ByteArray	= new ByteArray();
				abuf.writeUTFBytes("count");
			
			addArguments(abuf);
		}
		
		internal function addArguments(abuf:ByteArray):void
		{
			var asiz:uint	= abuf.length;
			
			_bytes.position = _bytes.length;
			_bytes.writeUnsignedInt(asiz);
			_bytes.writeBytes(abuf);
			
			setRnumAddOne();
		}
		
		internal function catBytes(bytes:ByteArray):void
		{
			_bytes.position	= _bytes.length;
			_bytes.writeBytes(bytes);
		}
		
		private function addFunName(name:String):void
		{
			var nsiz:uint	= name.length;
			var opts:uint	= getOpts(name);
			var rnum:uint	= 0;
			
			_bytes.position	= 2;
			_bytes.writeUnsignedInt(nsiz);
			_bytes.writeUnsignedInt(opts);
			_bytes.writeUnsignedInt(rnum);
			_bytes.writeUTFBytes(name);
		}
		
		private function getOpts(type:String):uint
		{
			var ret:uint;
			switch(type){
				case TokyoTyrantQueryFunctionName.SEARCH:
				case TokyoTyrantQueryFunctionName.GET:
					ret	= 1;
					break;
				case TokyoTyrantQueryFunctionName.OUT:
				case TokyoTyrantQueryFunctionName.PUT:
					ret	= 0;
					break;
				default:
					ret = 0;
			}
			
			return ret;
		}
		
		private function setRnumAddOne():void
		{
			_rnum++;
			
			_bytes.position	= 10;
			_bytes.writeUnsignedInt(_rnum);
		}
	}
}